//==================================================================
/// PlayerCar.cpp
///
/// Created by Davide Pasca - 2010/3/30
/// See the file "license.txt" that comes with this project for
/// copyright info. 
//==================================================================

#include "stdafx.h"
#include "PlayerCar.h"

//==================================================================
static const float ACCHACK = 1.0f / 1024;

//==================================================================
void PlayerCar::Animate(
					const AnimParams &par,
					float &out_carXAccel,
					float &out_roadXAccel )
{
	if ( par.mLeftIsDown || par.mRightIsDown )
	{
		if ( par.mLeftIsDown )
			if ( mWheelPos > -32 )
				mWheelPos -= 8;

		if ( par.mRightIsDown )
			if ( mWheelPos < 32 )
				mWheelPos += 8;
	}
	else
	{
		if ( mWheelPos > 0 )
			mWheelPos -= 8;
		else
		if ( mWheelPos < 0 )
			mWheelPos += 8;
	}

	// kinematics
	mSpeed += mAccel;

	//mpoMyCar->_dx = 0;
	int step_wd = 25;

	out_carXAccel = -(step_wd * mSpeed) / 100 * mWheelPos / 32.0f;

	float t = mSpeed;
	t = t * t;
	out_roadXAccel = -par.mCurXAcc * t * (1.0f / 256);

	if ( par.mUpIsDown )
		out_roadXAccel /= 4;
	else
		out_roadXAccel /= 9;

	if (
		(out_carXAccel > (ACCHACK * 25000) &&
		out_roadXAccel < (ACCHACK * -30000) &&
		mWheelPos <= -PlayerCar::WHEEL_MAX) ||

		(out_carXAccel < (ACCHACK * -25000) &&
		out_roadXAccel > (ACCHACK * 30000) &&
		mWheelPos >=  PlayerCar::WHEEL_MAX)
		)
	{
		out_carXAccel = -out_roadXAccel;
		++mDriftVal;
		//mpoPO->add( "drifting = YES" );
	}
	else
	{
		//mpoPO->add( "drifting = NO" );
		mDriftVal = 0;
	}

	// if there is any collision, then apply
	// some braking force
	if ( par.mEdgeCollisionVal )
	{
		mAccel -= 400 * ACCHACK;
	}

	// handle up and down controls (accel and brake)
	if ( par.mUpIsDown )
	{
		mAccel += 100 * ACCHACK;
	}
	else
	if ( par.mDownIsDown )
	{
		mAccel -= 200 * ACCHACK;
	}
	else
	{
		mAccel -= 20 * ACCHACK;
		if ( mAccel < -(400 * ACCHACK) )
			mAccel = -400 * ACCHACK;
	}

	// clamp accel
	if ( mAccel > (1000 * ACCHACK) )
		mAccel = 1000 * ACCHACK;

	if ( mAccel < (-2000 * ACCHACK) )
		mAccel = -2000 * ACCHACK;

	if ( par.mpCollVehicle != NULL )
	{
		mAccel -= 100 * ACCHACK * par.mCollVehicleStrength;
		mSpeed = par.mpCollVehicle->mSpeed * 0.9f;
	}

	// clamp speed
	if ( mSpeed <= 0 && mAccel < 0 )
	{
		mSpeed = 0;
		mAccel = 0;
	}

	if ( mSpeed > 140 && mAccel > 0 )
	{
		mSpeed = 140;
		mAccel = 0;
	}

	// ----
	mIsNoseDiving = false;

	// if was noseup or nosedown then the frame_x is 2 (neutral)
	int curRendFrame = mRendFrame;
	if ( curRendFrame > 40 )
		curRendFrame = 20;

	mRendFrame = (mWheelPos * 20 / PlayerCar::WHEEL_MAX) + 20;

	if ( mRendFrame < curRendFrame )
		mRendFrame = curRendFrame - 2;
	else
	if ( mRendFrame > curRendFrame )
		mRendFrame = curRendFrame + 2;
	else
	{
		if ( !par.mLeftIsDown && !par.mRightIsDown )
		{
			// nose down
			if ( par.mpCollVehicle != NULL ||
				(par.mDownIsDown && mSpeed > 5 && mAccel < 0) )
			{
				mRendFrame = 60;
				mIsNoseDiving = true;
			}
			else
			// nose up
			if ( mSpeed <= 50 && mAccel > (200*ACCHACK)  )
			{
				mRendFrame = 50;
				mIsNoseDiving = true;
			}
		}
	}

}

//==================================================================
void PlayerCar::Draw(
				graphics			&g,
				const transformer	&xformer,
				particler			&smokeLPart,
				particler			&smokeRPart,
				sprite				&smokeSptr,
				sprite				&myCarSptr,
				const Vec3			&myCarPosCS
				)
{
	if ( mIsNoseDiving || mDriftVal > 0 )
	{
		if ( !smokeLPart.is_active() )
			smokeLPart.begin(
						0.5f, 60,
						Vec3( 0, 2, 0			),
						Vec3( 14, 1, 0			),
						Vec3( -3.f, 2,  -2		),
						Vec3( 3.f, 0,  0		),
						Vec3( .92f, .92f, .92f	),
						&smokeSptr );

		if ( !smokeRPart.is_active() )
			smokeRPart.begin(
						0.5f, 60,
						Vec3( 0, 2, 0			),
						Vec3( 14, 1, 0			),
						Vec3( -3.f, 2,  -2		),
						Vec3( 3.f, 0,  0		),
						Vec3( .92f, .92f, .92f	),
						&smokeSptr );
	}
	else
	{
		smokeLPart.end();
		smokeRPart.end();
	}

	Vec3	posSS;
	xformer.Project( myCarPosCS, posSS );

	myCarSptr.draw( g, mRendFrame, (int)posSS.x, (int)posSS.y, 1.0f );

	smokeLPart.draw( g );
	smokeRPart.draw( g );
}
